package com.dieusoft.box.info.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dieusoft.box.info.entity.JzxDefaultCostDetails;
import com.dieusoft.box.info.entity.JzxInfo;
import com.dieusoft.box.info.service.IJzxDefaultCostDetailsService;
import com.dieusoft.box.info.service.IJzxInfoService;
import com.dieusoft.box.info.vo.JzxInfoPage;
import com.dieusoft.box.yardrate.service.IYardInfoService;
import com.google.common.base.Joiner;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.aspect.annotation.PermissionData;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.transaction.Transactional;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @Description: 集装箱管理
 * @Author: jeecg-boot
 * @Date: 2020-10-16
 * @Version: V1.0
 * <p>
 * 2021-04-27对新增、编辑和导入的数据进行箱号唯一校验
 */
@Api(tags = "集装箱管理")
@RestController
@RequestMapping("/box.info/jzxInfo")
@Slf4j
public class JzxInfoController {
    @Autowired
    private IJzxInfoService jzxInfoService;
    @Autowired
    private IJzxDefaultCostDetailsService jzxDefaultCostDetailsService;

    @Autowired
    private IYardInfoService yardInfoService;

    /**
     * 分页列表查询
     *
     * @param jzxInfo
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    @PermissionData(pageComponent = "jzxinfo/JzxInfoList")
    @AutoLog(value = "集装箱管理-分页列表查询")
    @ApiOperation(value = "集装箱管理-分页列表查询", notes = "集装箱管理-分页列表查询")
    @GetMapping(value = "/list")
    public Result<?> queryPageList(JzxInfo jzxInfo,
                                   @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                   @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                   HttpServletRequest req) {
        QueryWrapper<JzxInfo> queryWrapper = QueryGenerator.initQueryWrapper(jzxInfo, req.getParameterMap());
        Page<JzxInfo> page = new Page<JzxInfo>(pageNo, pageSize);
        IPage<JzxInfo> pageList = jzxInfoService.page(page, queryWrapper);


        //箱管列表底部统计查询
        List<JzxInfo> list = jzxInfoService.list(queryWrapper);
        Map<String, List<JzxInfo>> groupData = list.stream().collect(Collectors.groupingBy(JzxInfo::getContainerType));
        StringBuffer groupSb = new StringBuffer();
        AtomicInteger i = new AtomicInteger();
        for (Map.Entry<String, List<JzxInfo>> m : groupData.entrySet()) {
            groupSb.append(m.getKey()).append("：").append(m.getValue().size()).append("台，");
            i.addAndGet(m.getValue().size());
        }
        groupSb.insert(0, "箱子总数：" + i.get() + "台，");
        return Result.OK(pageList).success(groupSb.toString().substring(0, groupSb.toString().length() - 1));
    }

    /**
     * 添加
     *
     * @param jzxInfoPage
     * @return
     */
    @AutoLog(value = "集装箱管理-添加")
    @ApiOperation(value = "集装箱管理-添加", notes = "集装箱管理-添加")
    @PostMapping(value = "/add")
    public Result<?> add(@RequestBody JzxInfoPage jzxInfoPage) {
        JzxInfo jzxInfo = new JzxInfo();
        BeanUtils.copyProperties(jzxInfoPage, jzxInfo);
        try {
            jzxInfoService.save(jzxInfo);
            return Result.OK("添加成功", jzxInfo.getId());
        } catch (DuplicateKeyException e) {
            return Result.error(jzxInfo.getContainerNumber() + "的箱号已存在，不能重复新增。");
        }
    }

    /**
     * 批量添加
     *
     * @param jzxInfoPage
     * @return
     */
    @AutoLog(value = "集装箱管理-批量添加")
    @ApiOperation(value = "集装箱管理-批量添加", notes = "集装箱管理-批量添加")
    @PostMapping(value = "/addmany")
    public Result<?> addMany(@RequestBody JzxInfoPage jzxInfoPage) {
        log.info("批量添加的数量:{}", jzxInfoPage.getCount());
        final List<JzxInfo> jzxInfoList = new ArrayList<>();
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        Date date = new Date();
        for (int i = 0; i < jzxInfoPage.getCount(); i++) {
            JzxInfo jzxInfo = new JzxInfo();
            BeanUtils.copyProperties(jzxInfoPage, jzxInfo);
            jzxInfo.setId(IdWorker.getIdStr());
            jzxInfo.setCreateBy(sysUser.getUsername());
            jzxInfo.setSysOrgCode(sysUser.getOrgCode());
            jzxInfo.setCreateTime(date);
            jzxInfoList.add(jzxInfo);
        }
        jzxInfoService.insertMany(jzxInfoList);
        return Result.OK("添加成功！");
    }

    /**
     * 编辑
     *
     * @param jzxInfoPage
     * @return
     */
    @AutoLog(value = "集装箱管理-编辑")
    @ApiOperation(value = "集装箱管理-编辑", notes = "集装箱管理-编辑")
    @PostMapping(value = "/edit")
    public Result<?> edit(@RequestBody JzxInfoPage jzxInfoPage) {
        JzxInfo jzxInfo = new JzxInfo();
        BeanUtils.copyProperties(jzxInfoPage, jzxInfo);
        JzxInfo jzxInfoEntity = jzxInfoService.getById(jzxInfo.getId());
        if (jzxInfoEntity == null) {
            return Result.error("未找到对应数据");
        }
        //如果状态为已用状态再判断进出场时间是否有。根据进出场时间计算出总堆存天数 超期堆存天数 超期堆存费
        // TODO 改为前端计算
//        int daysBetween = 0;
//        int overstockingDays = 0;
//        if (jzxInfoEntity.getStatus() != 1 && null != jzxInfo.getInTime() && null != jzxInfo.getOutTime()) {
//            daysBetween = daysBetween(jzxInfo.getInTime(), jzxInfo.getOutTime()) + 1;
//            overstockingDays = daysBetween - jzxInfo.getFreeDepositDays();
//            jzxInfo.setTotalDepositDays(daysBetween);
//            jzxInfo.setOverstockingDays(overstockingDays);
//        }
//        if (StringUtils.isNotBlank(jzxInfo.getContainerPlace())) {
//            YardInfo yardInfo = yardInfoService.getById(jzxInfo.getContainerPlace());
//            List<JzxDefaultCostDetails> jzxDefaultCostDetailsList = jzxDefaultCostDetailsService.selectByMainId(yardInfo.getId());
//            String containerType = jzxInfo.getContainerType();
//            for (JzxDefaultCostDetails defaultCostDetails : jzxDefaultCostDetailsList) {
//                if (defaultCostDetails.getUnit().equals(containerType)) {
//                    jzxInfo.setOverdueStorageFee((defaultCostDetails.getPrice().multiply(new BigDecimal(overstockingDays > 0 ? overstockingDays : 0))).toString());
//                    break;
//                }
//            }
//        }
//        jzxInfoService.updateMain(jzxInfo, jzxInfoPage.getJzxDefaultCostDetailsList());
        try {
            jzxInfoService.updateById(jzxInfo);
            return Result.OK("编辑成功", jzxInfo.getId());
        } catch (DuplicateKeyException e) {
            return Result.error(jzxInfo.getContainerNumber() + "的箱号已存在，不能重复新增。");
        }
    }

//    public static int daysBetween(Date smdate, Date bdate) {
//        Calendar cal = Calendar.getInstance();
//        cal.setTime(smdate);
//        long time1 = cal.getTimeInMillis();
//        cal.setTime(bdate);
//        long time2 = cal.getTimeInMillis();
//        long between_days = (time2 - time1) / (1000 * 3600 * 24);
//        return Integer.parseInt(String.valueOf(between_days));
//    }

    /**
     * 设置状态
     *
     * @return
     */
    @AutoLog(value = "集装箱管理-设置状态")
    @ApiOperation(value = "集装箱管理-设置状态", notes = "集装箱管理-设置状态")
    @PostMapping(value = "/setstatus")
    public Result<?> setStatus(String id, Integer status) {
        JzxInfo jzxInfoEntity = jzxInfoService.getById(id);
        if (jzxInfoEntity == null) {
            return Result.error("未找到对应数据");
        }
        jzxInfoEntity.setStatus(status);
        jzxInfoEntity.setUpdateTime(new Date());
        jzxInfoService.updateById(jzxInfoEntity);
        return Result.OK("设置成功!");
    }

    /**
     * 通过id删除
     *
     * @param id
     * @return
     */
    @AutoLog(value = "集装箱管理-通过id删除")
    @ApiOperation(value = "集装箱管理-通过id删除", notes = "集装箱管理-通过id删除")
    @DeleteMapping(value = "/delete")
    public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
        jzxInfoService.delMain(id);
        return Result.OK("删除成功!");
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @AutoLog(value = "集装箱管理-批量删除")
    @ApiOperation(value = "集装箱管理-批量删除", notes = "集装箱管理-批量删除")
    @DeleteMapping(value = "/deleteBatch")
    public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
        this.jzxInfoService.delBatchMain(Arrays.asList(ids.split(",")));
        return Result.OK("批量删除成功！");
    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     */
    @AutoLog(value = "集装箱管理-通过id查询")
    @ApiOperation(value = "集装箱管理-通过id查询", notes = "集装箱管理-通过id查询")
    @GetMapping(value = "/queryById")
    public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
        JzxInfo jzxInfo = jzxInfoService.getById(id);
        if (jzxInfo == null) {
            return Result.error("未找到对应数据");
        }
        return Result.OK(jzxInfo);

    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     */
    @AutoLog(value = "集装箱标准费用通过主表ID查询")
    @ApiOperation(value = "集装箱标准费用主表ID查询", notes = "集装箱标准费用-通主表ID查询")
    @GetMapping(value = "/queryJzxDefaultCostDetailsByMainId")
    public Result<?> queryJzxDefaultCostDetailsListByMainId(@RequestParam(name = "id", required = true) String id) {
        List<JzxDefaultCostDetails> jzxDefaultCostDetailsList = jzxDefaultCostDetailsService.selectByMainId(id);
        return Result.OK(jzxDefaultCostDetailsList);
    }

    /**
     * 根据费用名称查询标准费用
     *
     * @param id
     * @return
     */
    @AutoLog(value = "根据费用名称查询标准费用")
    @ApiOperation(value = "根据费用名称查询标准费用", notes = "集装箱标准费用-根据费用名称查询标准费用")
    @GetMapping(value = "/querycostdetailbycostname")
    public Result<?> getCostDetailByMainIdAndCostName(@RequestParam(name = "id", required = true) String id,
                                                      @RequestParam(name = "costName", required = true) String costName) {
        List<JzxDefaultCostDetails> jzxDefaultCostDetailsList = jzxDefaultCostDetailsService.selectCostNameByMainId(id, costName);
        return Result.OK(jzxDefaultCostDetailsList);
    }

    /**
     * 导出excel
     *
     * @param request
     * @param jzxInfo
     */
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(HttpServletRequest request, JzxInfo jzxInfo) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        // Step.1 组装查询条件查询数据
        QueryWrapper<JzxInfo> queryWrapper = QueryGenerator.initQueryWrapper(jzxInfo, request.getParameterMap());
        queryWrapper.eq("sys_org_code", sysUser.getOrgCode());
        //Step.2 获取导出数据
        List<JzxInfo> queryList = jzxInfoService.list(queryWrapper);
        // 过滤选中数据
        String selections = request.getParameter("selections");
        List<JzxInfo> jzxInfoList = new ArrayList<JzxInfo>();
        if (oConvertUtils.isEmpty(selections)) {
            jzxInfoList = queryList;
        } else {
            List<String> selectionList = Arrays.asList(selections.split(","));
            jzxInfoList = queryList.stream().filter(item -> selectionList.contains(item.getId())).collect(Collectors.toList());
        }

        // Step.3 组装pageList
        List<JzxInfoPage> pageList = new ArrayList<JzxInfoPage>();
        for (JzxInfo main : jzxInfoList) {
            JzxInfoPage vo = new JzxInfoPage();
            BeanUtils.copyProperties(main, vo);
            vo.setCnStatus(vo.getStatus() == 1 ? "可用" : "不可用");
            if (null == vo.getOverdueStorageFeeUnit()) {
                vo.setOverdueStorageFee(vo.getOverdueStorageFeeCurrency() + vo.getOverdueStorageFee());
            } else {
                vo.setOverdueStorageFee(vo.getOverdueStorageFeeUnitCurrency() + vo.getOverdueStorageFeeUnit());
            }
            if (null == vo.getPolDesc()) {
                vo.setPolDesc(vo.getPol());
            }
            if (null == vo.getPodDesc()) {
                vo.setPodDesc(vo.getPod());
            }
            List<JzxDefaultCostDetails> jzxDefaultCostDetailsList = jzxDefaultCostDetailsService.selectByMainId(main.getId());
            vo.setJzxDefaultCostDetailsList(jzxDefaultCostDetailsList);
            pageList.add(vo);
        }

        String[] cols = request.getParameter("field").split(",");
        List filterCols = new ArrayList();
        for (String str : cols) {
            if (StringUtils.isNoneBlank(str) && !"action".equals(str) && !"id".equals(str) && !"status".equals(str)) {
                filterCols.add(str.replaceAll("_dictText", ""));
            }
        }
        String exportFields = Joiner.on(",").join(filterCols);
        // Step.4 AutoPoi 导出Excel
        ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
        mv.addObject(NormalExcelConstants.FILE_NAME, "集装箱数据");
        mv.addObject(NormalExcelConstants.CLASS, JzxInfoPage.class);
        mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("集装箱数据", "导出人:" + sysUser.getRealname(), "集装箱数据"));
        mv.addObject(NormalExcelConstants.DATA_LIST, pageList);
        mv.addObject(NormalExcelConstants.EXPORT_FIELDS, exportFields);
        return mv;
    }

    /**
     * 通过excel导入数据
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    @Transactional(rollbackOn = Exception.class)
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile file = entity.getValue();// 获取上传文件对象
            ImportParams params = new ImportParams();
            params.setTitleRows(2);
            params.setHeadRows(1);
            params.setNeedSave(true);
            try {
                List<JzxInfoPage> list = ExcelImportUtil.importExcel(file.getInputStream(), JzxInfoPage.class, params);
                boolean isGo = false;
                LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
                List<String> repeatData = new LinkedList<>();
                for (JzxInfoPage page : list) {
                    JzxInfo po = new JzxInfo();
                    BeanUtils.copyProperties(page, po);
//                    jzxInfoService.saveMain(po, page.getJzxDefaultCostDetailsList());
                    //判断非空字段是否有值
                    if (null == po.getContainerNumber() || null == po.getContainerType()) {
                        isGo = true;
                        break;
                    }
                    //查询是否存在相同的箱号
                    QueryWrapper<JzxInfo> jzxInfoQueryWrapper = new QueryWrapper<>();
                    jzxInfoQueryWrapper.eq("container_number", po.getContainerNumber());
                    jzxInfoQueryWrapper.eq("sys_org_code", sysUser.getOrgCode());
                    JzxInfo ji = jzxInfoService.getOne(jzxInfoQueryWrapper);
                    if (null != ji) {
                        repeatData.add(po.getContainerNumber());
                    }
                }

                if (isGo) {
                    return Result.error("表格中存在箱型或箱号为空的数据");
                }
                if (repeatData.size() > 0) {
                    return Result.error("下面箱号已存在不能重复添加。" + Joiner.on(",").join(repeatData));
                }
                for (JzxInfoPage page : list) {
                    JzxInfo po = new JzxInfo();
                    BeanUtils.copyProperties(page, po);
//                    jzxInfoService.saveMain(po, page.getJzxDefaultCostDetailsList());
                    try {
                        jzxInfoService.save(po);
                    } catch (DuplicateKeyException e) {
                        return Result.error(po.getContainerNumber() + "的箱号已存在，不能重复新增。");
                    }
                }
                return Result.OK("文件导入成功！数据行数:" + list.size());
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                return Result.error("文件导入失败:" + e.getMessage());
            } finally {
                try {
                    file.getInputStream().close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return Result.OK("文件导入失败！");
    }

}
